# -*- coding: utf-8 -*-
class TaskController < ApplicationController
  # 共通レイアウト定義
  layout "mainpage", :except=>[:block_list, :block_infolist, :dlg_index, :dlg_new, :dlg_edit, :dlg_create, :dlg_update, :dlg_destroy, :dlg_report]

  # フィルタ定義
  before_filter :login_required, :except=>[:sync_air] # ログインチェック

  # 追加ヘルパー定義
  helper :project

  # コントローラー使用のヘルパー定義
  include ApplicationHelper
  include ProjectHelper
  include TaskHelper

  include ProjectItem

  #
  #=== タスク一覧表示
  #
  #ログイン中のユーザが担当となっているタスクの一覧を取得して表示する．
  #
  #同時にその他の担当者も取得する
  #
  def block_list
    #-----------------------------
    # ログイン中ユーザーが担当している
    # タスクのリストを取得
    # ※担当者、構成データも同時に取得
    #-----------------------------
    conditions = "dat_projects.valid_flg = 1 AND dat_projectusers.user_id = #{session['user']['id']}"
    if ! params[:project_id].nil?
      conditions += " AND dat_projectcomps.project_id = #{params[:project_id]}"
    end
    
    opt = {
      :conditions => conditions,
      :include    => [{:dat_taskusers=>:dat_projectuser}, {:dat_projectcomp=>:dat_project}], 
      :order      => "dat_tasks.id desc"
    }
    @tasks = DatTask.find(:all, opt)
  end

  #
  #タスクコントローラのデフォルトアクション
  def index
  end

  #
  #=== タスク完了登録アクション
  #
  #タスクを完了状態に更新する
  #
  def update_complete
    unless params[:task].nil?
      #-----------------------------
      # 登録済みのタスクを取得する
      #-----------------------------
      task = DatTask.find(params[:task][:id])
      #-----------------------------
      # 属性値設定
      #-----------------------------
      if task.progress_kbn != 3
        # 完了扱いに変更
        task.progress_kbn = 3
      else
        # 現在、完了の場合は、元に戻す
        task.progress_kbn = 0 ;
      end
      #-----------------------------
      # タスク情報保存
      #-----------------------------
      unless task.save
        result_for_json( false, 'update_complete error', {} )
        return
      end
    end
    render :text => result_for_json(true, '', {})
  end

  #
  #タスク編集ダイアログのためのデフォルトアクション
  #
  def dlg_index
  end

  #
  #タスク新規作成（ダイアログ用）
  #
  #空のタスクを生成し，タスク新規情報としてJSON形式で返す
  #* task_kbn: 1をセット(タスクのtask_kbnが1であるため)
  #
  def dlg_new
    #-----------------------------
    # 新規タスクオブジェクト生成
    #-----------------------------
    @task = DatTask.new
    #-----------------------------
    # 新規プロジェクト構成データオブジェクト生成
    # ※分類パラメータを初期設定（:dlg_tsk_edit_comp）
    #-----------------------------
    @projectcomp = DatProjectcomp.new(params[:dlg_tsk_edit_comp])
    @projectcomp.task_kbn = "1" ;

    #-----------------------------
    # 参加ユーザー情報の取得
    #-----------------------------
    # プロジェクト参加ユーザーリストを取得
    projectusers = object_for_projectusers(@projectcomp.project_id)
    # タスク参加ユーザーリストを取得
    taskusers = object_for_taskusers(@task.id)

    # 依頼者はログインユーザーデフォルト
    projectuser = DatProjectuser.find_by_user_id_and_project_id( session['user']['id'], @projectcomp.project_id )
#    projectuser = DatProjectuser.find_by_user_id(session['user']['id'])
    @task.client_user_id = projectuser.id

    #-----------------------------
    # JSONデータ生成
    #-----------------------------
    result  = {
      :task         => @task.attributes,
      :projectcomp  => @projectcomp.attributes,
      :projectusers => projectusers,
      :taskusers    => taskusers
    }
    render :text => result_for_json(true, '', result)
  end

  #
  #=== タスク編集ダイアログ
  #
  #指定されたタスクのデータを取得し，json形式で返却する
  #
  def dlg_edit
    if params[:dlg_tsk_edit_comp][:id].nil? || params[:dlg_tsk_edit_comp][:id] == ""
      #-----------------------------
      # IDが指定されていない場合、新規作成処理へリダイレクト
      #-----------------------------
      redirect_to :action => 'dlg_new'
    else
      return unless my_item?(params[:dlg_tsk_edit_comp][:id])# check permission
      
      #-----------------------------
      # 登録済みプロジェクト構成情報を取得
      # ※プロジェクト、タスク情報も同時に取得
      #-----------------------------
      opt = {
        :conditions => [" dat_projectcomps.id = ? ", params[:dlg_tsk_edit_comp][:id]],
        :include    => [:dat_project, :dat_task]
      }
      @projectcomp = DatProjectcomp.find(:first, opt)
      @task        = @projectcomp.dat_task
      #-----------------------------
      # 参加ユーザー情報の取得
      #-----------------------------
      # プロジェクト参加ユーザーリストを取得
      if @task
        projectusers = object_for_projectusers(@projectcomp.project_id)
        # タスク参加ユーザーリストを取得
        taskusers = object_for_taskusers(@task.id)
        logger.debug taskusers.inspect
      end
      #-----------------------------
      # JSONデータ生成
      #-----------------------------
      result  = {
        :task         => @task ? @task.attributes : nil,
        :projectcomp  => @projectcomp.attributes,
        :projectusers => projectusers,
        :taskusers    => taskusers
      }
      render :text => result_for_json(true, '', result)
    end
  end

  #
  #=== タスクの新規作成
  #
  #フォームから渡されたパラメータを元にプロジェクトアイテムを新規作成し，
  #同時にタスクを作成する．
  #
  def dlg_create
    session_user_id = session["user"]["id"] 
    #-----------------------------
    # 新規プロジェクト構成データ生成
    #-----------------------------
    # フォームパラメータから新規プロジェクト構成オブジェクトを生成
    @projectcomp = DatProjectcomp.new(params[:dlg_tsk_edit_comp])
    @projectcomp.task_kbn = "1" ;
    @projectcomp.create_user_id = session_user_id
    @projectcomp.update_user_id = session_user_id
    @projectcomp.last_operation_kbn = 2

    #-----------------------------
    # 新規タスクデータ生成
    #-----------------------------
    # フォームパラメータから新規タスクオブジェクトを生成
    @task = DatTask.new( params[:dlg_tsk_edit_task] )
    @task.create_user_id = session_user_id
    @task.update_user_id = session_user_id
    @task.last_operation_kbn = 2
    @projectcomp.dat_task = @task

    #-----------------------------
    # 追加位置（行番号）決定
    #-----------------------------
    if ! params[:dlg_tsk_edit_base_id].nil? && ! params[:dlg_tsk_edit_base_id].empty?
      # 基準となるプロジェクト構成IDが指定されている場合
      # 基準データの後ろに追加
      base_projectcomp = DatProjectcomp.find(params[:dlg_tsk_edit_base_id])
      @projectcomp.line_no = base_projectcomp.line_no + 1
    else
      # 基準となるプロジェクト構成IDが指定されていない場合
      # プロジェクトの最後尾に追加
      max_line_no = DatProjectcomp.maximum( :line_no,
                                            :conditions=>["project_id = ? ", @projectcomp.project_id]
                                          )
      max_line_no = 0 if max_line_no.nil?
      @projectcomp.line_no = max_line_no + 1
    end

    #-----------------------------
    # タスク担当者生成
    #-----------------------------
    # タスクユーザー指定時、タスクユーザーオブジェクトを生成
    if ! params[:dlg_tsk_edit_taskusers].nil?
      for puser in params[:dlg_tsk_edit_taskusers][:projectuser_id]
        # buildにて生成し、ここでは保存しない
        taskuser = @task.dat_taskusers.build(:projectuser_id=>puser)
        taskuser.create_user_id = session_user_id
      end
    end

    #-----------------------------
    # プロジェクト構成データ保存実施
    #-----------------------------
    if ! @projectcomp.save
      message = error_message_to_string(@projectcomp, {:item_name=>app_localized_message(:label, :task_name)})
      unless @task.errors.empty?
        message += "\n" unless message == ""
        message += error_message_to_string(@task)
      end
      render :text => result_for_json( false, message, {} )
      return
    end

    #-----------------------------
    # 行番号更新
    #-----------------------------
    if ! params[:dlg_tsk_edit_base_id].nil? && ! params[:dlg_tsk_edit_base_id].empty?
      # 間に挿入した場合、以降の構成データの行番号をずらす
      if ! DatProjectcomp.update_all(" line_no = line_no + 1 ", 
                                   [ "project_id = ? AND line_no >= ? AND id <> ? ",
                                       @projectcomp.project_id,
                                       @projectcomp.line_no,
                                       @projectcomp.id ]
                                     )
        # ????? エラー処理 ????? 
        @projectcomp.destroy
        render :text => result_for_json( false, app_localized_message(:error, :task_lineno_save_error), {} )
        return
      end
    end

    #-----------------------------
    # JSONデータ生成
    #-----------------------------
    result  = {
      :resulthtml   => ""
    }
    render :text => result_for_json(true, '', result)
  end

  #
  #=== タスク更新
  #
  #指定されたタスクのデータをフォームパラメータを元に更新する
  #
  def dlg_update
    session_user_id = session["user"]["id"] 
    
    return unless my_item?(params[:dlg_tsk_edit_comp][:id])# check permission
    
    #-----------------------------
    # 登録済みオブジェクトを取得
    #-----------------------------
    @projectcomp = DatProjectcomp.find(:first,
                          :conditions => [" dat_projectcomps.id = ? ", params[:dlg_tsk_edit_comp][:id]],
                          :include =>[{:dat_task=>[:dat_taskusers]}] )
    @projectcomp.update_user_id = session_user_id
    @projectcomp.last_operation_kbn = 3
    @task = @projectcomp.dat_task
    @task.update_user_id = session_user_id
    @task.last_operation_kbn = 3

    #-----------------------------
    # タスク担当者生成
    #-----------------------------
    # タスクユーザー指定時、タスクユーザーオブジェクトを生成
    @task.dat_taskusers.clear  #一旦削除
    unless params[:dlg_tsk_edit_taskusers].nil?
      for puser in params[:dlg_tsk_edit_taskusers][:projectuser_id]
        # buildにて生成し、ここでは保存しない
        taskuser = @task.dat_taskusers.build(:projectuser_id=>puser)
        taskuser.create_user_id = session_user_id
      end
    end

    #-----------------------------
    # プロジェクト構成データ保存実施
    #-----------------------------
    #params[:dlg_tsk_edit_comp].delete(:id);
    @projectcomp.dat_task.update_attributes(params[:dlg_tsk_edit_task])
    unless @projectcomp.update_attributes(params[:dlg_tsk_edit_comp])
      # ????? エラー処理 ????? 
      message = error_message_to_string(@projectcomp, 
                                        {:item_name=>app_localized_message(:label, :task_name)})
      logger.debug @projectcomp.errors.inspect
      render :text => result_for_json( false, message, {} )
      return
    end
    #-----------------------------
    # タスクデータ保存実施
    #-----------------------------
    unless @task.update_attributes(params[:dlg_tsk_edit_task])
      # ????? エラー処理 ????? 
      message = error_message_to_string(@task)
      render :text => result_for_json( false, message, {} )
      return
    end

    #-----------------------------
    # JSONデータ生成
    #-----------------------------
    result  = {
      :resulthtml   => ""
    }
    render :text => result_for_json(true, '', result)
  end

  #
  #=== タスクの削除
  #
  #指定されたプロジェクトアイテムを削除する．
  #関連指定されたタスクも同時に削除される．
  #
  def dlg_destroy
    return unless my_item?(params[:dlg_tsk_edit_comp][:id])# check permission

    unless DatProjectcomp.destroy(params[:dlg_tsk_edit_comp][:id])
      render :text => result_for_json(false, app_localized_message(:error, :task_destroy_error), {})
    else
      result  = {
        :resulthtml => ""
      }
      render :text => result_for_json( true, '', result )
    end
  end


  #
  #=== タスクの進捗報告ダイアログ
  #
  #タスク報告ダイアログのためのアクション
  #
  def dlg_report
  end

  #
  #=== 進捗編集ダイアログ
  #
  #指定されたタスク進捗報告データを取得して，編集ダイアログを表示する
  #
  def dlg_report_edit
    if params[:dlg_tsk_report_task][:id].nil? || params[:dlg_tsk_report_task][:id] == ""
      render :text => result_for_json(false, '', result)
    else
      #-----------------------------
      # 登録済みタスク情報を取得
      # ※プロジェクト構成情報も同時に取得
      #-----------------------------
      opt = {
        :conditions => [" dat_tasks.id = ? ", params[:dlg_tsk_report_task][:id]],
        :include    => [:dat_projectcomp]
      }
      @task = DatTask.find(:first, opt)
      @projectcomp = @task.dat_projectcomp
  
      @task.report_date = Date.today if @task.report_date.nil?
      
      # JSONデータ生成
      result  = {
        :task        => @task.attributes,
        :projectcomp => @projectcomp.attributes
      }
      render :text => result_for_json(true, '', result)
    end
  end

  #
  #=== タスク報告を行う
  #
  #指定されたタスクに対する進捗報告を行う．
  #進捗報告新規作成，または更新する
  #
  def dlg_report_update
    session_user_id = session["user"]["id"] 
    #-----------------------------
    # 登録済みオブジェクトを取得
    #-----------------------------
    report_params = params[:dlg_tsk_report_task]
    logger.debug report_params.inspect
    comp_id = report_params[:id]
    
    r = false
    message = ''
    result  = {}
    if my_item?(comp_id)
      o = {:include => :dat_task}
      comp = DatProjectcomp.find(comp_id, o)
      
      last_operation_kbn, rate = report_params[:progres_kbn].to_i == 1 ? [3, 10] : [1, report_params[:progress_rate]]
      rate = 'progress_rate_' + rate
      # update projectcomp
      comp.update_user_id     = session_user_id
      comp.last_operation_kbn = last_operation_kbn
      # update task
      report_params.delete(:id)
      task = comp.dat_task
      task.attributes         = report_params
      task.update_user_id     = session_user_id
      task.last_operation_kbn = last_operation_kbn
      
      if comp.save && task.save
        p = {
          :task_id        => task.id,
          :msg_code       => rate,
          :report_date    => report_params[:report_date],
          :content        => report_params[:memo],
          :update_user_id => session_user_id
        }
        history = DatTaskhistory.new(p)
        unless history.save
          message = error_message_to_string(history)
        else
          r = true
          result = {:resulthtml => ''}
        end
      else
        message = error_message_to_string(comp)
      end
    else
      message = 'Permission Denied'
    end
    render :text => result_for_json(r, message, result)
  end


  # dlg_confirm
  # @return task confirm
  def dlg_confirm
    id = params[:id]#projectcomp.id
    if my_item?(id)
      o = {
        :include => {:dat_task => {:dat_taskhistories => :update_user}},
        :order   => 'dat_taskhistories.report_date DESC'
      }
      comp = DatProjectcomp.find(id, o)
      dat_histories = comp.dat_task.dat_taskhistories
      histories = dat_histories.map do |h|
        attr = h.attributes
        attr['content']       = h.content.gsub(/(\r\n|\r|\n)/, '') if h.content
        attr['report_date']   = format_date_year(h.report_date)
        attr['progress_rate'] = app_localized_message(:label, attr['msg_code'])
        attr['report_user']   = h(h.update_user.user_name ||= h.update_user.email)
        attr
      end
      task = comp.dat_task
      comp_attr = comp.attributes
      task_attr = task.attributes
      task_attr['complete_date'] = format_date_year(task.complete_date)
      task_attr['report_date']   = format_date_year(task.report_date)
      task_attr['progress_rate'] = app_localized_message(:label, 'progress_rate_' + task.progress_rate.to_s)
      r = {:comp => comp_attr, :task => task_attr, :histories => histories}
      render :text => result_for_json(true, '', r)
    else
      render :text => result_for_json(false, 'Permission Denied', {})
    end
  end

  private
  def format_date_year(date)
    if date
      today = Date.today
      format =  today.year == date.year ? '%m/%d' : '%Y/%m/%d'
      date.strftime(format)
    end
  end
end
